#include "bsp_elcdif.h"
#include "bsp_gpio.h"
#include "bsp_delay.h"
#include "bsp_led.h"
#include "bsp_beep.h"
#include "bsp_uart.h"

struct _lcd_dev lcd;
extern const unsigned char gImage_1[1152000];
extern const unsigned char gImage_2[1152000];

void elcdif_init(void){

	unsigned short lcdid = elcdif_read_lcdID();
	printf(UART1 , "LCD ID=%#X\r\n", lcdid);
	elcdif_io_init();
	elcdif_reset();
	lcd.pixsize  = 4;
	lcd.backcolor = LCD_WHITE;	/* 背景色为白色 */
	lcd.forecolor = LCD_BLACK;	/* 前景色为黑色 */
	lcd.fram_buffer = LCD_FRAMEBUF_ADDR;
    if(lcdid == ATK4342) {
		lcd.height = 272;	
		lcd.width = 480;
		lcd.vspw = 1;
		lcd.vbp = 8;
		lcd.vfp = 8;
		lcd.hspw = 1;
		lcd.hbp = 40;
		lcd.hfp = 5; 	
		elcdif_clk_init(27, 8, 8);	/* 初始化LCD时钟 10.1MHz */
	} else if(lcdid == ATK4384) {
		lcd.height = 480;	
		lcd.width = 800;
		lcd.vspw = 3;
		lcd.vbp = 32;
		lcd.vfp = 13;
		lcd.hspw = 48;
		lcd.hbp = 88;
		lcd.hfp = 40;
		elcdif_clk_init(42, 4, 8);	/* 初始化LCD时钟 31.5MHz,42,4,8 */
	} else if(lcdid == ATK7084) {
		lcd.height = 480;	
		lcd.width = 800;
		lcd.vspw = 1;
		lcd.vbp = 23;
		lcd.vfp = 22;
		lcd.hspw = 1;
		lcd.hbp = 46;
		lcd.hfp = 210;	
		elcdif_clk_init(30, 3, 7);	/* 初始化LCD时钟 34.2MHz */
	} else if(lcdid == ATK7016) {
		lcd.height = 600;	
		lcd.width = 1024;
		lcd.vspw = 3;
		lcd.vbp = 20;
		lcd.vfp = 12;
		lcd.hspw = 20;
		lcd.hbp = 140;
		lcd.hfp = 160;
		elcdif_clk_init(32, 3, 5);	/* 初始化LCD时钟 51.2MHz */
	} else if(lcdid == ATK1018) {
		lcd.height = 800;	
		lcd.width = 1280;
		lcd.vspw = 3;
		lcd.vbp = 10;
		lcd.vfp = 10;
		lcd.hspw = 10;
		lcd.hbp = 80;
		lcd.hfp = 70;
		elcdif_clk_init(35, 3, 5);	/* 初始化LCD时钟 56MHz */
	} else if(lcdid == ATKVGA) {  
		lcd.height = 768;	
		lcd.width = 1366;
		lcd.vspw = 3;
		lcd.vbp = 24;
		lcd.vfp = 3;
		lcd.hspw = 143;
		lcd.hbp = 213;
		lcd.hfp = 70;
		elcdif_clk_init(32, 3, 3);	/* 初始化LCD时钟 85MHz */
	}
	
	
	LCDIF->CTRL = (1<<19) | (1<<17) | (0<<14) | (0<<12) | (3<<10) | (3<<8) | (1<<5) | (0<<1);
	LCDIF->CTRL1 = (7<<16);
	LCDIF->VDCTRL0 = (0<<29) | (1<<28) | (0<<27) | (0<<26) | (0<<25) | (1<<24) | (1<<21) | (1<<20) | (lcd.vspw<<0);
	LCDIF->VDCTRL1 = lcd.vspw + lcd.vbp + lcd.height + lcd.vfp;
	LCDIF->VDCTRL2 = (lcd.hspw << 18) | (lcd.hspw + lcd.hbp + lcd.width + lcd.hfp);
	LCDIF->VDCTRL3 = ((lcd.hspw + lcd.hbp)<<16) | (lcd.vspw + lcd.vbp);
	LCDIF->VDCTRL4 = (1<<18) | (lcd.width);
	LCDIF->TRANSFER_COUNT = (lcd.height<<16) | (lcd.width);
	LCDIF->CUR_BUF = lcd.fram_buffer;
	LCDIF->NEXT_BUF = lcd.fram_buffer;


	elcdif_enable();
	lcd_clear(LCD_WHITE);
	delay(100);
	
}

/*读取LCDID*/
unsigned short elcdif_read_lcdID(void){

	unsigned char LCDID = 0;

	/*打开模拟开关，也即设置LCD_VSYNC引脚高电平，使D7、D15、D23引脚同elcdif模块相连*/
	IOMUXC_SetPinMux(IOMUXC_LCD_VSYNC_GPIO3_IO03, 0);			//设置引脚复用
	IOMUXC_SetPinConfig(IOMUXC_LCD_VSYNC_GPIO3_IO03, 0X10B0);	//设置引脚电气属性
	gpio_pin_config_t LCD_VSYNC_io_config;
	LCD_VSYNC_io_config.direction = gpio_output;
	LCD_VSYNC_io_config.output = 1;
	gpio_init(GPIO3, 3, &LCD_VSYNC_io_config);

	/*将D7、D15、D23复用为普通IO以读取LCD的ID*/
	IOMUXC_SetPinMux(IOMUXC_LCD_DATA07_GPIO3_IO12, 0);		/* B7(M2) */
	IOMUXC_SetPinMux(IOMUXC_LCD_DATA15_GPIO3_IO20, 0);		/* G7(M1) */
	IOMUXC_SetPinMux(IOMUXC_LCD_DATA23_GPIO3_IO28, 0);		/* R7(M0) */

	IOMUXC_SetPinConfig(IOMUXC_LCD_DATA07_GPIO3_IO12, 0xF080);	
	IOMUXC_SetPinConfig(IOMUXC_LCD_DATA15_GPIO3_IO20, 0xF080);
	IOMUXC_SetPinConfig(IOMUXC_LCD_DATA23_GPIO3_IO28, 0xF080);  

	gpio_pin_config_t idio_config;
	idio_config.direction = gpio_input;
	gpio_init(GPIO3, 12, &idio_config);
	gpio_init(GPIO3, 20, &idio_config);
	gpio_init(GPIO3, 28, &idio_config);

	/*读取三个引脚的返回值，即为LCDID*/
	LCDID = (unsigned char)gpio_read_pin(GPIO3 , 28);
	LCDID |= ((unsigned char)gpio_read_pin(GPIO3 , 20) << 1);
	LCDID |= ((unsigned char)gpio_read_pin(GPIO3 , 12) << 2);

	if(LCDID==0)return ATK4342;		//4.3寸屏,480*272分辨率
	else if(LCDID==1)return ATK7084;	//7寸屏,800*480分辨率
	else if(LCDID==2)return ATK7016;	//7寸屏,1024*600分辨率
	else if(LCDID==4)return ATK4384;	//4寸屏,800*480分辨率
	else if(LCDID==5)return ATK1018;	//10.1寸屏,1280*800分辨率		
	else if(LCDID==7)return ATKVGA;   //VGA模块，1366*768分辨率
	else return 0;

}

/*初始化LCD的IO*/
void elcdif_io_init(void){
    /* 1、IO初始化复用功能 */
	IOMUXC_SetPinMux(IOMUXC_LCD_DATA00_LCDIF_DATA00,0);
	IOMUXC_SetPinMux(IOMUXC_LCD_DATA01_LCDIF_DATA01,0);
	IOMUXC_SetPinMux(IOMUXC_LCD_DATA02_LCDIF_DATA02,0);
	IOMUXC_SetPinMux(IOMUXC_LCD_DATA03_LCDIF_DATA03,0);
	IOMUXC_SetPinMux(IOMUXC_LCD_DATA04_LCDIF_DATA04,0);
	IOMUXC_SetPinMux(IOMUXC_LCD_DATA05_LCDIF_DATA05,0);
	IOMUXC_SetPinMux(IOMUXC_LCD_DATA06_LCDIF_DATA06,0);
	IOMUXC_SetPinMux(IOMUXC_LCD_DATA07_LCDIF_DATA07,0);
	IOMUXC_SetPinMux(IOMUXC_LCD_DATA08_LCDIF_DATA08,0);
	IOMUXC_SetPinMux(IOMUXC_LCD_DATA09_LCDIF_DATA09,0);
	IOMUXC_SetPinMux(IOMUXC_LCD_DATA10_LCDIF_DATA10,0);
	IOMUXC_SetPinMux(IOMUXC_LCD_DATA11_LCDIF_DATA11,0);
	IOMUXC_SetPinMux(IOMUXC_LCD_DATA12_LCDIF_DATA12,0);
	IOMUXC_SetPinMux(IOMUXC_LCD_DATA13_LCDIF_DATA13,0);
	IOMUXC_SetPinMux(IOMUXC_LCD_DATA14_LCDIF_DATA14,0);
	IOMUXC_SetPinMux(IOMUXC_LCD_DATA15_LCDIF_DATA15,0);
	IOMUXC_SetPinMux(IOMUXC_LCD_DATA16_LCDIF_DATA16,0);
	IOMUXC_SetPinMux(IOMUXC_LCD_DATA17_LCDIF_DATA17,0);
	IOMUXC_SetPinMux(IOMUXC_LCD_DATA18_LCDIF_DATA18,0);
	IOMUXC_SetPinMux(IOMUXC_LCD_DATA19_LCDIF_DATA19,0);
	IOMUXC_SetPinMux(IOMUXC_LCD_DATA20_LCDIF_DATA20,0);
	IOMUXC_SetPinMux(IOMUXC_LCD_DATA21_LCDIF_DATA21,0);
	IOMUXC_SetPinMux(IOMUXC_LCD_DATA22_LCDIF_DATA22,0);
	IOMUXC_SetPinMux(IOMUXC_LCD_DATA23_LCDIF_DATA23,0);

	IOMUXC_SetPinMux(IOMUXC_LCD_CLK_LCDIF_CLK,0);	
	IOMUXC_SetPinMux(IOMUXC_LCD_ENABLE_LCDIF_ENABLE,0);	
	IOMUXC_SetPinMux(IOMUXC_LCD_HSYNC_LCDIF_HSYNC,0);
	IOMUXC_SetPinMux(IOMUXC_LCD_VSYNC_LCDIF_VSYNC,0);

    IOMUXC_SetPinMux(IOMUXC_GPIO1_IO08_GPIO1_IO08,0);			/* 背光BL引脚      */

	/* 2、配置LCD IO属性	
	 *bit 16:0 HYS关闭
	 *bit [15:14]: 0 默认22K上拉
	 *bit [13]: 0 pull功能
	 *bit [12]: 0 pull/keeper使能 
	 *bit [11]: 0 关闭开路输出
	 *bit [7:6]: 10 速度100Mhz
	 *bit [5:3]: 111 驱动能力为R0/7
	 *bit [0]: 1 高转换率
	 */
	IOMUXC_SetPinConfig(IOMUXC_LCD_DATA00_LCDIF_DATA00,0xB9);
	IOMUXC_SetPinConfig(IOMUXC_LCD_DATA01_LCDIF_DATA01,0xB9);
	IOMUXC_SetPinConfig(IOMUXC_LCD_DATA02_LCDIF_DATA02,0xB9);
	IOMUXC_SetPinConfig(IOMUXC_LCD_DATA03_LCDIF_DATA03,0xB9);
	IOMUXC_SetPinConfig(IOMUXC_LCD_DATA04_LCDIF_DATA04,0xB9);
	IOMUXC_SetPinConfig(IOMUXC_LCD_DATA05_LCDIF_DATA05,0xB9);
	IOMUXC_SetPinConfig(IOMUXC_LCD_DATA06_LCDIF_DATA06,0xB9);
	IOMUXC_SetPinConfig(IOMUXC_LCD_DATA07_LCDIF_DATA07,0xB9);
	IOMUXC_SetPinConfig(IOMUXC_LCD_DATA08_LCDIF_DATA08,0xB9);
	IOMUXC_SetPinConfig(IOMUXC_LCD_DATA09_LCDIF_DATA09,0xB9);
	IOMUXC_SetPinConfig(IOMUXC_LCD_DATA10_LCDIF_DATA10,0xB9);
	IOMUXC_SetPinConfig(IOMUXC_LCD_DATA11_LCDIF_DATA11,0xB9);
	IOMUXC_SetPinConfig(IOMUXC_LCD_DATA12_LCDIF_DATA12,0xB9);
	IOMUXC_SetPinConfig(IOMUXC_LCD_DATA13_LCDIF_DATA13,0xB9);
	IOMUXC_SetPinConfig(IOMUXC_LCD_DATA14_LCDIF_DATA14,0xB9);
	IOMUXC_SetPinConfig(IOMUXC_LCD_DATA15_LCDIF_DATA15,0xB9);
	IOMUXC_SetPinConfig(IOMUXC_LCD_DATA16_LCDIF_DATA16,0xB9);
	IOMUXC_SetPinConfig(IOMUXC_LCD_DATA17_LCDIF_DATA17,0xB9);
	IOMUXC_SetPinConfig(IOMUXC_LCD_DATA18_LCDIF_DATA18,0xB9);
	IOMUXC_SetPinConfig(IOMUXC_LCD_DATA19_LCDIF_DATA19,0xB9);
	IOMUXC_SetPinConfig(IOMUXC_LCD_DATA20_LCDIF_DATA20,0xB9);
	IOMUXC_SetPinConfig(IOMUXC_LCD_DATA21_LCDIF_DATA21,0xB9);
	IOMUXC_SetPinConfig(IOMUXC_LCD_DATA22_LCDIF_DATA22,0xB9);
	IOMUXC_SetPinConfig(IOMUXC_LCD_DATA23_LCDIF_DATA23,0xB9);

	IOMUXC_SetPinConfig(IOMUXC_LCD_CLK_LCDIF_CLK,0xB9);
	IOMUXC_SetPinConfig(IOMUXC_LCD_ENABLE_LCDIF_ENABLE,0xB9);
	IOMUXC_SetPinConfig(IOMUXC_LCD_HSYNC_LCDIF_HSYNC,0xB9);
	IOMUXC_SetPinConfig(IOMUXC_LCD_VSYNC_LCDIF_VSYNC,0xB9);

    IOMUXC_SetPinConfig(IOMUXC_GPIO1_IO08_GPIO1_IO08,0x10b0);	

	/* 背光BL引脚，打开背光 */
	gpio_pin_config_t lcd_backlight_config;
    lcd_backlight_config.direction = gpio_output;			
	lcd_backlight_config.output = 1; 							
	gpio_init(GPIO1, 8, &lcd_backlight_config);						
}

void elcdif_clk_init(unsigned char DIV_SELECT , unsigned char LCDIF1_PRED , unsigned char LCDIF1_PODF){

	/*设置PLL5频率*/
	CCM_ANALOG->PLL_VIDEO_NUM = 0;
	CCM_ANALOG->PLL_VIDEO_DENOM = 0;
	CCM_ANALOG->PLL_VIDEO = 0;					//必须要先清空PLL_VIDEO
	CCM_ANALOG->PLL_VIDEO |= (DIV_SELECT<<0);

	/*设置POST_DIV_SELECT分频*/
	CCM_ANALOG->PLL_VIDEO |= (2<<19);

	/*设置VIDEO_DIV分频*/
	CCM_ANALOG->MISC2 &= ~(3 << 30);
	CCM_ANALOG->MISC2 |= (0<<30);

	/*设置LCDIF1_PRE_CLK_SEL时钟源*/
	CCM->CSCDR2 &= ~(7 << 15); 
	CCM->CSCDR2 |= (2 << 15);

	/*设置LCDIF1_PRED分频*/
	CCM->CSCDR2 &= ~(7 << 12);
	CCM->CSCDR2 |= ((LCDIF1_PRED - 1) << 12);

	/*设置LCDIF1_PODF分频*/
	CCM->CBCMR &= ~(7 << 23);
	CCM->CBCMR |= ((LCDIF1_PODF - 1) << 23);

	/*设置LCDIF1_PODF分频*/
	CCM->CSCDR2 &= ~(7 << 9);
	CCM->CSCDR2 |= (0 << 9);
	
	/*使能video PLL*/
	CCM_ANALOG->PLL_VIDEO |= (1<<13);

}

void elcdif_reset(void){
	LCDIF->CTRL = 1<<31;
	delay(10);
	LCDIF->CTRL = 0<<31;
}

void elcdif_enable(void){
	LCDIF->CTRL |= 1<<0;
}

void lcd_clear(unsigned int color){
	unsigned int num = lcd.height * lcd.width;
	unsigned int i = 0;
	unsigned int * stdr = (unsigned int *)lcd.fram_buffer;
	for(i = 0 ; i<num ; i++){
		stdr[i] = color;
	}	
}

void lcd_draw_picture(unsigned char *picture){
	unsigned int num = lcd.height * lcd.width;
	unsigned int i = 0;
	unsigned int * stdr = (unsigned int *)lcd.fram_buffer;
	for(i = 0 ; i<num ; i++){
		stdr[i] = picture[i*3];
		stdr[i] = (stdr[i] << 8) + picture[i*3 + 1];
		stdr[i] = (stdr[i] << 8) + picture[i*3 + 2];
	}
}

void lcd_draw_love(unsigned char *picture){
	unsigned int num = lcd.height * lcd.width;
	unsigned int i = 0;
	unsigned int * stdr = (unsigned int *)lcd.fram_buffer;
	for(i = 0 ; i<num ; i++){
		if(num<20*800){
			picture[i*3] = 0xff;
			picture[i*3 + 1] = 0xff;
			picture[i*3 + 2] = 0xff;
			stdr[i] = picture[i*3];
			stdr[i] = (stdr[i] << 8) + picture[i*3 + 1];
			stdr[i] = (stdr[i] << 8) + picture[i*3 + 2];
		}
		if(num>=20*800){
			stdr[i] = picture[i*3];
			stdr[i] = (stdr[i] << 8) + picture[i*3 + 1];
			stdr[i] = (stdr[i] << 8) + picture[i*3 + 2];
		}
		
	}
}

void lcd_draw_dot(unsigned int x , unsigned int y , unsigned int color){
	unsigned int * stdr = (unsigned int *)lcd.fram_buffer;
	stdr[((x-1)+(y-1)*lcd.width)]= color;
	stdr[(x+(y-1)*lcd.width)]= color;
	stdr[((x+1)+(y-1)*lcd.width)]= color;

	stdr[((x-1)+(y*lcd.width))]= color;
	stdr[((x)+(y*lcd.width))]= color;
	stdr[((x+1)+(y*lcd.width))]= color;

	stdr[((x-1)+(y+1)*lcd.width)]= color;
	stdr[(x+(y+1)*lcd.width)]= color;
	stdr[((x+1)+(y+1)*lcd.width)]= color;
}

void lcd_draw_line(unsigned int xs , unsigned int ys , unsigned int xe , unsigned int ye, unsigned int color){
	int xd = xe - xs;
	int yd = ye - ys;
	int i = 0;
	for(i = 0 ; i<=1000 ; i++){
		unsigned int xn = xs + xd*i/1000;
		unsigned int yn = ys + yd*i/1000;
		lcd_draw_dot(xn , yn , color);
	}
}

unsigned int lcd_read_dot(unsigned int x , unsigned int y){
	unsigned int * stdr = (unsigned int *)lcd.fram_buffer;
	return stdr[y*lcd.width+x];
}

inline void lcd_drawpoint(unsigned short x,unsigned short y,unsigned int color)
{ 
  	*(unsigned int*)((unsigned int)lcd.fram_buffer + 
		             lcd.pixsize * (lcd.width * y+x))=color;
}
